home *** CD-ROM | disk | FTP | other *** search
- ;----------------------------------------------------------------
- ; RAMVIEW: A memory-resident memory-viewer.
- ; Frank Dever & David Thomas, WindowDOS Associates
- ;----------------------------------------------------------------
- CR EQU 13 ;carriage return
- LF EQU 10 ;line feed
- U_ARR EQU 72 ;up arrow
- D_ARR EQU 80 ;down arrow
- PGUP EQU 73 ;page up
- PGDN EQU 81 ;page down
- L_ARR EQU 75 ;left arrow
- R_ARR EQU 77 ;right arrow
- HOME EQU 71 ;home
- END_KEY EQU 79 ;end
- ;----------------------------------------------------------------------
- HOTKEY EQU 58h ;F12
- SHIFT_MASK EQU 0 ;Unshifted
- INT9_BUSY EQU 1
- INT10_BUSY EQU 2
- INT16_BUSY EQU 4
- VIDEO_BUF EQU TopStack - 4260 ;Buffer & Stack after code
- ;----------------------------------------------------------------------
- _TEXT SEGMENT PARA PUBLIC 'CODE'
- ASSUME CS:_TEXT,DS:_TEXT
- ORG 100h
- BEGIN: JMP START
- ;Resident Data
- INSTALLED DB "RAMVIEW 2.00 (c) 1992 PC Magazine",9,9,254
- DB " The Hotkey is F12 ",254,CR,LF,"$",8,32,8,26
- UNINSTALLED DB "RAMVIEW Uninstalled",CR,LF,"$"
-
- DISABLE DB 0 ;flag for de-installation
-
- LABEL0 DB " ABS SEG OFF 0 1 2 3 4 5 6 7"
- DB " 8 9 A B C D E F ASCII",0
-
- START_DISPLAY DB " GOTO ADDRESS: 0000:0000",0
-
- COMMANDLINE DB "(G)oto (H)ex Search (A)scii Search (N)ext"
- DB " ",24," ",25," PgUp PgDn Home End Esc ",0
-
- CURSOR_POS DW 0
- CURSOR_TYPE DW 0607H ;for turning cursor on/off
- START_OFFSET DW 0 ;top addr shown on screen
- START_SEGMENT DW 0
- END_OFFSET DW 0FH ;last segment in search
- END_SEGMENT DW 0FFFFH ;fixed to ffff:f
- SEARCH_SEGMENTS DW 0 ;# segments to search
- SEARCH_BYTES DW 0 ;# bytes left after search
- HEX_SIEVE DB " " ;hex with space
- ADDR_SIEVE DB "01234567890ABCDEF" ;hex without space
- CHAR_SIEVE DB 0 ;all characters
- ASCII_SEARCH_PROMPT DB "ASCII Search String: ",0;ascii search prompt
- HEX_SEARCH_PROMPT DB "HEX Search String: ",0 ;hex search prompt
- ASCII_SEARCH_AREA DB 20 DUP (" "),0 ;ascii search string
- HEX_SEARCH_AREA DB 20 DUP (" "),0 ;hex search string
- LAST_SEARCH_STRING DW 0 ;pointer to last string
- LAST_STRING_LENGTH DW 0 ;last string length
- OUR_SS DW 0
- OUR_SP DW 0
- THEIR_SS DW 0
- THEIR_SP DW 0
- ADDR_INT9H DD 0
- ADDR_INT10H DD 0
- BIOS_SEG DW 40H
- DIFF DW 0 ;# of chars on a line > 80
- ROW DW 0 ;display row counter
- BUSY DB 0
- ;Resident Code
- ;----------------------------------------------------------------------
- START PROC NEAR
- CLD
- CALL PROGRAM_ALREADY_IN
- JNZ NOT_IN ;Install or
- CALL UNINSTALL ;Un-Install
- MOV AX,4C01h
- INT 21h
- NOT_IN: MOV OUR_SS,CS ;Set Stack Segment
- MOV OUR_SP,OFFSET TopStack ;and Pointer
- CALL INSTALL
- MOV DX,OFFSET INSTALLED
- MOV AH,9 ;Say Installed
- INT 21h
- MOV DX,OFFSET TopStack+15 ;Convert Length
- MOV CL,4 ;into Paragraphs
- SHR DX,CL
- MOV AX,3100h ;TSR Code, Video
- INT 21h ;Buffer and Stack
- START ENDP
- ;----------------------------------------------------------------------
- INT10H PROC FAR
- OR CS:BUSY,INT10_BUSY ;recursion protection
- PUSHF
- CALL CS:ADDR_INT10H
- PUSHF
- AND CS:BUSY,NOT(INT10_BUSY)
- POPF
- RET 2 ;preserve flags
- INT10H ENDP
- ;----------------------------------------------------------------------
- INT9H PROC FAR
- STI
- PUSH AX ;Preserve working register
- CMP CS:DISABLE,-1 ;If DISABLED
- JE NOT_US ;Then Do NOTHING
- IN AL,60h ;Else Get Key Port KEY
- CMP AL,HOTKEY ;If NOT HotKey
- JNE NOT_US ;Then Do NOTHING
- MOV AH,2 ;Else Get Shift Status
- INT 16h
- AND AL,0Fh
- CMP AL,SHIFT_MASK ;If NOT Shift Combination
- JNE NOT_US ;Then Do NOTHING
- IN AL,61h ;Else RESET
- MOV AH,AL ;KEYBOARD
- OR AL,80h
- OUT 61h,AL
- MOV AL,AH ;After a
- JMP SHORT $+2 ;DELAY
- OUT 61h,AL
- CLI
- MOV AL,20h ;RESET
- OUT 20h,AL ;INT Controller
- STI
- CMP CS:BUSY,0 ;AVOID
- JNE WE_ARE_BUSY ;RE-ENTRANCE
- OR CS:BUSY,INT9_BUSY
- CALL ADJUST_FOR_VIDEO_MODE ;If NOT Text or => 80 cols
- JC CANT_POP_UP ;Then Can't Display Properly
- CALL TSRMAIN ;Else Display 80x25 RamView
- CANT_POP_UP:
- CLI ;Hold Interrupts while
- AND CS:BUSY,NOT(INT9_BUSY) ;Reset RamView NOT Busy
- WE_ARE_BUSY:
- POP AX
- IRET
- NOT_US:
- POP AX
- JMP CS:ADDR_INT9H
- INT9H ENDP
- ;----------------------------------------------------------------------
- ADJUST_FOR_VIDEO_MODE PROC NEAR
- PUSH BX
- MOV AH,15 ;Get present mode
- INT 10h
- CMP AH,80 ;If Below 80 Columns
- JB BAD_MODE ;Then Wrong Mode
- MOV BYTE PTR CS:DIFF,AH ;Else CALCULATE
- SUB CS:BYTE PTR DIFF,80 ;EXTRA ROOM
- CMP AL,7 ;If NOT Mono
- JNE TRY_COLOR ;Then COLOR?
- MODE_OK:
- CLC
- POP BX
- RET
- TRY_COLOR:
- CMP AL,3 ;If 1 - 3
- JBE MODE_OK ;Then 80x25
- BAD_MODE: ;Else NOT Ok
- STC
- POP BX
- RET
- ADJUST_FOR_VIDEO_MODE ENDP
- ;-----------------------------------------------------------------
- ;main routine called by pressing hot key
- ;-----------------------------------------------------------------
- TSRMAIN PROC NEAR
- CALL SWAPIN ;new stack
- MOV AX,CS ;our data segment
- MOV DS,AX
- CALL SAVE_CURSOR ;save cursor
- CALL CURSOR_OFF ;turn cursor off
- CALL SAVE_SCREEN ;save screen
- CALL CLEAR_SCREEN ;clear screen
- XOR AX,AX ;row 0
- MOV BX,AX ;col 0
- MOV SI,OFFSET LABEL0 ;bottom line
- CALL DISPLAY_STRING ;show header line
- NEXT_SCREEN:
- CALL BODY ;put hex display up
- MOV AX,24 ;last row
- XOR BX,BX ;column 0
- MOV SI,OFFSET COMMANDLINE
- CALL DISPLAY_STRING ;show it
- CALL MENU ;go get keystroke
- JNC NEXT_SCREEN ;until esc is pressed
-
- CALL RESTORE_SCREEN ;put screen back
- CALL CURSOR_ON ;turn cursor on
- CALL RESTORE_CURSOR
- CALL SWAPOUT ;restore stack
- RET
- TSRMAIN ENDP
- ;-----------------------------------------------------------------
- ;cursor routines
- ;-----------------------------------------------------------------
- SAVE_CURSOR PROC NEAR
- MOV ES,BIOS_SEG
- MOV AX,ES:[60H] ;get present cursor type
- MOV CURSOR_TYPE,AX ;save it
- CALL GETPOS
- MOV CURSOR_POS,DX
- RET
- SAVE_CURSOR ENDP
- ;----------------------------------------------------------------------
- RESTORE_CURSOR PROC NEAR
- MOV DX,CURSOR_POS
- CALL SETPOS
- RET
- RESTORE_CURSOR ENDP
- ;----------------------------------------------------------------------
- SETPOS PROC NEAR
- MOV AH,2 ;set cursor position
- XOR BH,BH ;active page
- INT 10H ;set cursor position to dx
- RET
- SETPOS ENDP
- ;----------------------------------------------------------------------
- GETPOS PROC NEAR
- MOV AH,3 ;get cursor position
- XOR BH,BH ;active page
- INT 10H ;get cursor position in dx
- RET
- GETPOS ENDP
- ;----------------------------------------------------------------------
- CURSOR_OFF PROC NEAR
- PUSH CX
- MOV CX,2B0CH ;turn off cursor value
- CALL SETCUR
- POP CX
- RET
- CURSOR_OFF ENDP
- ;----------------------------------------------------------------------
- CURSOR_ON PROC NEAR
- PUSH CX
- MOV CX,CURSOR_TYPE ;turn on cursor value
- CALL SETCUR
- POP CX
- RET
- CURSOR_ON ENDP
- ;----------------------------------------------------------------------
- SETCUR PROC NEAR
- PUSH AX
- MOV AH,1 ;function to set cursor shape
- INT 10H
- POP AX
- RET
- SETCUR ENDP
- ;-----------------------------------------------------------------
- ;screen routines
- ;-----------------------------------------------------------------
- SAVE_SCREEN PROC NEAR
- PUSH DS ;save data segment
- XOR AX,AX
- MOV BX,AX
- CALL CALC_SCRN_ADDR ;address of (0,0)
- MOV SI,OFFSET VIDEO_BUF
- PUSH DS
- PUSH ES
- POP DS
- POP ES
- XCHG DI,SI
- MOV BX,25
- SAVE_NEXT_LINE:
- MOV CX,80 ;save an 80
- REP MOVSW ;word line
- ADD SI,CS:DIFF ;get video
- ADD SI,CS:DIFF ;next line
- DEC BX ;25 lines =
- JNZ SAVE_NEXT_LINE ;2000 words
- POP DS
- RET
- SAVE_SCREEN ENDP
- ;-----------------------------------------------------------------
- CLEAR_SCREEN PROC NEAR
- XOR AX,AX
- MOV BX,AX
- CALL CALC_SCRN_ADDR ;address of (0,0)
- MOV AX,0720H ;space with normal attribute
- MOV BX,24
- CLEAR_NEXT_LINE:
- MOV CX,80
- REP STOSW ;words
- ADD DI,CS:DIFF ;go to next
- ADD DI,CS:DIFF ;line
- DEC BX ;24 lines
- JNZ CLEAR_NEXT_LINE
- RET
- CLEAR_SCREEN ENDP
- ;-----------------------------------------------------------------
- RESTORE_SCREEN PROC NEAR
- XOR AX,AX
- MOV BX,AX
- CALL CALC_SCRN_ADDR ;address of (0,0)
- MOV SI,OFFSET VIDEO_BUF
- MOV BX,25
- RESTORE_NEXT_LINE:
- MOV CX,80 ;save 2000
- REP MOVSW ;words
- ADD DI,CS:DIFF ;go to next
- ADD DI,CS:DIFF ;line
- REP MOVSW ;words
- DEC BX ;25 lines
- JNZ RESTORE_NEXT_LINE
- RET
- RESTORE_SCREEN ENDP
- ;-----------------------------------------------------------------
- ;Stack Routines
- ;-----------------------------------------------------------------
- RETADDR DW 0
- SWAPIN PROC NEAR
- POP CS:RETADDR ;Save Caller's Address
- MOV CS:THEIR_SS,SS ;Save Their Stack
- MOV CS:THEIR_SP,SP
- MOV SS,CS:OUR_SS ;Switch to Our Stack
- MOV SP,CS:OUR_SP
- PUSH AX ;Preserve all registers
- PUSH BX
- PUSH CX
- PUSH DX
- PUSH SI
- PUSH DI
- PUSH ES
- PUSH DS
- PUSH BP
- JMP CS:RETADDR ;Return to Caller
- SWAPIN ENDP
- ;-----------------------------------------------------------------
- SWAPOUT PROC NEAR
- POP CS:RETADDR ;Save Caller's Address
- POP BP ;Restore All Registers
- POP DS
- POP ES
- POP DI
- POP SI
- POP DX
- POP CX
- POP BX
- POP AX
- MOV SS,CS:THEIR_SS ;Restore Caller's Stack
- MOV SP,CS:THEIR_SP
- JMP CS:RETADDR ;Return to Caller
- SWAPOUT ENDP
- ;-----------------------------------------------------------------
- ;clears last line
- ;-----------------------------------------------------------------
- CLEAR_LAST_LINE PROC NEAR
- MOV AX,24 ;row 24
- XOR BX,BX ;col 0
- CALL CALC_SCRN_ADDR ;get es:di for that address
- MOV CX,80 ;80 words
- MOV AX,0720H ;normal attribute spaces
- REP STOSW ;clear it
- RET
- CLEAR_LAST_LINE ENDP
- ;-----------------------------------------------------------------
- ;menu accept and key input
- ;-----------------------------------------------------------------
- MENU PROC NEAR
- NEXT_MENU_KEY:
- CALL GETKEY ;input a key
- CMP AH,2 ;if scan code below 2
- JBE QUIT_EXIT ;then key is ESCape
- NOT_ESC:
- AND AL,0DFH ;make all ascii caps
- CMP AL,"G" ;G)o
- JNZ NOT_GOTO
- CALL GO_TO ;get start addr
- JMP SHORT MENU_EXIT
- NOT_GOTO:
- CMP AL,"A" ;A)scii search
- JNZ NOT_ASCII_SEARCH
- CALL ASCII_SEARCH ;find ascii string
- JMP SHORT MENU_EXIT
- NOT_ASCII_SEARCH:
- CMP AL,"H" ;H)ex search
- JNZ NOT_HEX_SEARCH
- CALL HEX_SEARCH ;find hex string
- JMP SHORT MENU_EXIT
- NOT_HEX_SEARCH:
- CMP AL,"N" ;N)ext search
- JNZ NOT_NEXT_SEARCH
- CALL NEXT_SEARCH ;find next string
- JMP SHORT MENU_EXIT
- NOT_NEXT_SEARCH:
- CMP AH,U_ARR ;up arrow
- JNZ NOT_UP
- MOV AX,-10H
- JMP SHORT MOVEIT
- NOT_UP:
- CMP AH,HOME ;go to beginning of memory
- JNZ NOT_HOME
- MOV START_OFFSET,0
- MOV START_SEGMENT,0
- JMP SHORT MENU_EXIT
- NOT_HOME:
- CMP AH,END_KEY ;go to end of memory
- JNZ NOT_END
- MOV START_OFFSET,0FE90H ;top of last page
- MOV START_SEGMENT,0F000H
- JMP SHORT MENU_EXIT
- NOT_END:
- CMP AH,D_ARR ;down arrow
- JNZ NOT_DOWN
- MOV AX,10H
- JMP SHORT MOVEIT
- NOT_DOWN:
- CMP AH,PGUP ;page up
- JNZ NEXT_CHECK
- MOV AX,-170H
- JMP SHORT MOVEIT
- NEXT_CHECK:
- CMP AH,PGDN ;page down
- MOV AX,170H
- JZ MOVEIT
- JMP NEXT_MENU_KEY
- MOVEIT: CALL MOVE
- MENU_EXIT:
- CLC ;clear carry for exit
- QUIT_EXIT:
- RET
- MENU ENDP
- ;-----------------------------------------------------------------
- ;sets starting segment and offset for display
- ;-----------------------------------------------------------------
- MOVE PROC NEAR
- OR AX,AX ;is the movement signed
- JNS ADDIT ;no-add to seg:off
- NEG AX ;otherwise make positive
- SUB START_OFFSET,AX ;subtract from offset
- JNC MOVE_EXIT ;if no carry, done
- SUB START_SEGMENT,1000H ;else wrap segment
- JMP SHORT MOVE_EXIT
- ADDIT: ADD START_OFFSET,AX ;add movement to offset
- JNC MOVE_EXIT ;if no carry, done
- ADD START_SEGMENT,1000H ;else wrap segment
- MOVE_EXIT:
- RET
- MOVE ENDP
- ;-----------------------------------------------------------------
- ;ascii search routine
- ;-----------------------------------------------------------------
- ASCII_SEARCH PROC NEAR
- CALL CLEAR_LAST_LINE ;clear line for input
- MOV AX,24 ;last row
- XOR BX,BX ;first col
- MOV SI,OFFSET ASCII_SEARCH_PROMPT
- CALL DISPLAY_STRING ;show the prompt
- CALL STRLEN ;find out how long prompt is
- MOV DL,CL ;dl = col after prompt
- MOV DH,24 ;dx = row col
- MOV SI,OFFSET ASCII_SEARCH_AREA ;
- MOV CX,20 ;size of the string
- CALL CLEAR_BUF
- MOV DI,OFFSET CHAR_SIEVE ;pointer to sieve
- MOV BX," " ;get
- ;dx=row col,cx=size,bl=replace,si=prompt,di=sieve
- CALL INPUT
- MOV SI,OFFSET ASCII_SEARCH_AREA
- MOV LAST_SEARCH_STRING,SI ;save ptr to str for next
- CALL STRLEN ;how long?
- MOV LAST_STRING_LENGTH,CX ;save length for next
- JCXZ NO_SEARCH ;if not, dont search
- CALL SEARCH_MEM ;cx=length si=string
- NO_SEARCH:
- RET
- ASCII_SEARCH ENDP
- ;-----------------------------------------------------------------
- ;find next occurrence
- ;-----------------------------------------------------------------
- NEXT_SEARCH PROC NEAR
- MOV SI,LAST_SEARCH_STRING ;get address of last string
- MOV CX,LAST_STRING_LENGTH
- JCXZ NO_NEXT ;dont search
- ADD START_OFFSET,1 ;move over one to start
- JNC NOS_WRAP ;if it causes wrap,
- ADD START_SEGMENT,1000H ;wrap segment
- NOS_WRAP:
- CALL SEARCH_MEM ;search for next string
- NO_NEXT:
- RET
- NEXT_SEARCH ENDP
- ;-----------------------------------------------------------------
- ;hex search routine
- ;-----------------------------------------------------------------
- HEX_SEARCH PROC NEAR
- CALL CLEAR_LAST_LINE ;clear line for input
- MOV SI,OFFSET HEX_SEARCH_PROMPT
- MOV AX,24 ;last row
- XOR BX,BX ;first col
- CALL DISPLAY_STRING ;show the prompt
- CALL STRLEN ;find out how long prompt is
- MOV DL,CL ;dl = col after prompt
- MOV DH,24 ;dx = row col
- MOV SI,OFFSET HEX_SEARCH_AREA ;
- MOV CX,20 ;size of the string
- CALL CLEAR_BUF
- MOV DI,OFFSET HEX_SIEVE ;pointer to sieve
- MOV BX," " ;replacement char
- ;dx=row col,cx=size,bx=replace,si=prompt,di=sieve
- CALL INPUT
- MOV SI,OFFSET HEX_SEARCH_AREA
- CALL STRLEN ;length of search string
- CMP CL,1 ;must be at least two digits
- JBE NO_SEARCH ;otherwise search fails
- MOV LAST_SEARCH_STRING,SI ;save it
- MOV LAST_STRING_LENGTH,CX ;save length
- CALL ELIMINATE_BLANKS ;eliminate blanks in input
- CALL CONVERT_ASCII_HEX_TO_HEX_STRING ;string into hex
- MOV LAST_STRING_LENGTH,CX ;save length
- CALL SEARCH_MEM ;find it
- NOSEARCH:
- RET
- HEX_SEARCH ENDP
- ;-----------------------------------------------------------------
- ;clear ds:[si] with (cx) spaces
- ;-----------------------------------------------------------------
- CLEAR_BUF PROC NEAR
- PUSH CX
- PUSH SI
- CLEARIT: MOV BYTE PTR [SI]," "
- INC SI
- LOOP CLEARIT
- POP SI
- POP CX
- RET
- CLEAR_BUF ENDP
- ;-----------------------------------------------------------------
- ;translate ascii hex string to binary string, return size in cx
- ;-----------------------------------------------------------------
- CONVERT_ASCII_HEX_TO_HEX_STRING PROC NEAR
- PUSH SI ;save si for use in main
- MOV DI,SI ;duplicate si
- MOV BX,SI ;for later use
- NEXTC: LODSW ;get two ascii digits
- OR AL,AL ;are we at the end
- JZ C_EXIT ;if so, string is converted
- OR AH,AH ;in case wrong # digits
- JZ C_EXIT ;string is converted
- CALL ASCII_HEX_TO_HEX;translate ascii to binary
- STOSB ;put back in string
- JMP NEXTC ;get next two characters
- C_EXIT: XOR AL,AL ;clear al
- STOSB ;put terminator after this
- SUB DI,BX ;find out how many bytes
- LEA CX,[DI-1] ;we have converted
- POP SI ;restore important register
- RET
- CONVERT_ASCII_HEX_TO_HEX_STRING ENDP
- ;-----------------------------------------------------------------
- ;close up blanks in a string
- ;-----------------------------------------------------------------
- ELIMINATE_BLANKS PROC NEAR
- PUSH SI ;save si for main
- PUSH DS ;set ds:si and es:di to same
- POP ES
- MOV DI,SI
- NEXT_SQ: LODSB ;get character
- CMP AL," " ;if space
- JZ NEXT_SQ ;skip it
- STOSB ;otherwise store it
- OR AL,AL ;if zero
- JNZ NEXT_SQ ;done whole string
- SQUOZE: POP SI ;restore important register
- RET
- ELIMINATE_BLANKS ENDP
- ;-----------------------------------------------------------------
- ;go to command
- ;-----------------------------------------------------------------
- GO_TO PROC NEAR
- CALL CLEAR_LAST_LINE ;clear line for input
- MOV AX,24 ;row
- XOR BX,BX ;col
- MOV SI,OFFSET START_DISPLAY ;prompt
- CALL DISPLAY_STRING ;show it
- MOV DX,180FH ;row col
- MOV SI,OFFSET START_DISPLAY+15 ;destination
- MOV CX,9 ;size
- MOV DI,OFFSET ADDR_SIEVE ;sieve
- MOV BX,"0" ;replace char
- ;dx=row col,cx=size,bx=replace,si=prompt,di=sieve
- CALL INPUT
- MOV SI,OFFSET START_DISPLAY+15 ;ascii address
- MOV DI,OFFSET START_SEGMENT ;destination
- CALL CONVERT_ADDR ;32 bit ascii address to ptr
- CLC
- RET
- GO_TO ENDP
- ;-----------------------------------------------------------------
- ;convert ascii to binary segment and offset
- ; si=ascii di= pointer to destination
- ;-----------------------------------------------------------------
- CONVERT_ADDR PROC NEAR
- PUSH DS
- POP ES ;set es for stos
- INC DI
- CALL CONVERT_BYTE ;segment
- CALL CONVERT_BYTE
- INC SI ;colon
- CALL CONVERT_BYTE ;offset
- CALL CONVERT_BYTE
- RET
- CONVERT_ADDR ENDP
- ;-----------------------------------------------------------------
- CONVERT_BYTE PROC NEAR
- LODSW ;get two chars
- CALL ASCII_HEX_TO_HEX ;make hex
- MOV [DI],AL ;put in destination
- DEC DI ;set up for next character
- RET
- CONVERT_BYTE ENDP
- ;-----------------------------------------------------------------
- ;display main screen
- ;-----------------------------------------------------------------
- BODY PROC NEAR
- PUSH BP ;use the
- MOV BP,SP ;stack
- SUB SP,8 ;for temporary variables
- PUSH DS ;save ds for main routine
- LES BX,DWORD PTR START_OFFSET
- MOV [BP-2],BX ;save on stack
- MOV [BP-4],ES ;for later use
- CALL NORMALIZE ;change es:bx so 10h <= bx >=0
- MOV [BP-6],BX ;save value on stack
- MOV [BP-8],ES ;for later use
- MOV DS,[BP-4] ;get pointer
- MOV SI,[BP-2] ;to memory to display
- MOV CS:ROW,0 ;initialize row counter
- NEXT_LINE:
- INC CS:ROW ;next display row
- MOV AX,CS:ROW ;row
- XOR BX,BX ;col
- CALL CALC_SCRN_ADDR ;get es:di for that address
- MOV CX,[BP-8] ;hi part of norm 20 bit desc
- CALL WORD_OUT ;print it
- INC WORD PTR[BP-8] ;add 1 to seg = 16 bytes
- MOV AL,[BP-6] ;get lo part
- CALL HEX_TO_ASCII_HEX;convert to ascii
- XCHG AL,AH ;lowest significant nybble
- CALL CHAR_OUT ;print lo part of 'ABS' value
- CALL SPACE_OUT ;put separator
- MOV CX,[BP-4] ;segment being displayed
- CALL WORD_OUT ;print it
- MOV AL,":" ;followed
- CALL CHAR_OUT ;by a colon
- MOV CX,[BP-2] ;offset this line
- CALL WORD_SPACE ;print offset/space
- MOV CX,16 ;# characters to print
- MOV DX,SI ;save ptr to present line
- HEX_PART:
- LODSB ;get character
- CALL BYTE_OUT ;print two hex nybbles
- CALL SPACE_OUT ;print space
- LOOP HEX_PART ;all 16 hex digits
- MOV SI,DX ;get ptr to present line
- MOV CX,16 ;all 16 hex digits
- MOV AL,70H ;reverse the ascii part
- ASCII_PART:
- MOVSB ;print the ascii part
- STOSB ;reverse attribute on it
- LOOP ASCII_PART ;all 16 ascii chars
- ADD WORD PTR[BP-6],10H ;'ABS' + 16
- ADC WORD PTR[BP-8],0 ;
- ADD WORD PTR[BP-2],10H ;'SEG:OFF' + 16
- JNC NO_WRAP ;if it wraps
- ADD WORD PTR[BP-4],1000H ;wrap the segment
- MOV DS,[BP-4] ;get the data segment
- NO_WRAP:
- CMP CS:ROW,23 ;if not completely done
- JB NEXT_LINE ;do another
- POP DS ;restore ds for main routine
- ADD SP,8 ;clean off temporary variables
- POP BP ;restore bp
- RET
- BODY ENDP
- ;-----------------------------------------------------------------
- WORD_SPACE LABEL NEAR
- CALL WORD_OUT ;output two nybbles from cx
- SPACE_OUT LABEL NEAR
- MOV AL," " ;output a space
- JMP SHORT CHAR_OUT
- WORD_OUT LABEL NEAR
- MOV AL,CH ;get high nybble
- CALL BYTE_OUT ;print it
- MOV AL,CL ;get low nybble
- BYTE_OUT LABEL NEAR
- CALL HEX_TO_ASCII_HEX;cvt hex to two char nybbles
- STOSB ;print highest order nybble
- INC DI ;skip attribute
- MOV AL,AH ;get low order nybble
- CHAR_OUT LABEL NEAR
- STOSB ;print it
- INC DI ;skip attribute
- RET
- ;-----------------------------------------------------------------
- END_MINUS_START PROC NEAR
- LES BX,DWORD PTR START_OFFSET ;get start seg:off
- CALL NORMALIZE ;change es:bx so 10h <= bx >=0
- MOV AX,ES ;save normalized result
- MOV CX,BX ;for later use
- LES BX,DWORD PTR END_OFFSET ;get end seg:off
- CALL NORMALIZE ;change es:bx so 10h <= bx >=0
- MOV DX,ES ;get end segment
- SUB DX,AX ;calculate segments to search
- MOV SEARCH_SEGMENTS,DX
- MOV SEARCH_BYTES,BX ;# bytes in final segment
- MOV ES,AX ;set es:bx to
- MOV BX,CX ;start address
- RET
- END_MINUS_START ENDP
- ;-----------------------------------------------------------------
- ;make 20 bit pointer in es:bx from segment:offset in es:bx
- ;-----------------------------------------------------------------
- NORMALIZE PROC NEAR
- PUSH AX ;save these registers
- PUSH CX ;for main routine
- PUSH DX
- MOV AX,BX ;get the offset
- MOV CL,4 ;make into
- SHR AX,CL ;number of paragraphs
- MOV DX,ES ;get segment
- ADD DX,AX ;add in number of paragraphs
- MOV ES,DX ;back into segment
- SHL AX,CL ;calc offset into segment
- SUB BX,AX ;paras - paras mod 16
- POP DX ;retstore registers
- POP CX ;for main routine
- POP AX
- RET
- NORMALIZE ENDP
- ;-----------------------------------------------------------------
- ;si = string cx = string_size
- ;search for match of string beginning at start_segment
- ;-----------------------------------------------------------------
- SEARCH_MEM PROC NEAR
- MOV DI,CX ;save string size
- CALL END_MINUS_START ;calculate search length
- LOOK_AGAIN:
- CMP SEARCH_SEGMENTS,1000H ;more than or equal 64k?
- JAE MORE_THAN_ENOUGH ;if so, search 64k
- MOV AX,SEARCH_SEGMENTS ;otherwise, get what's left
- MOV CL,4
- SHL AX,CL ;segs*16 = bytes to search
- ADD AX,SEARCH_BYTES ;add in the last few bytes
- JMP SHORT LOOK ;and go look
- MORE_THAN_ENOUGH:
- MOV AX,-1 ;64k search
- LOOK: SUB AX,BX ;subtract initial offset
- JC SEARCH_NOT_FOUND ;offset < search size?
- SUB AX,DI ;subtract off string size
- JBE SEARCH_NOT_FOUND ;less than search size?
- CMP AX,DI ;amount left to search
- JB SEARCH_NOT_FOUND ;less than search size?
- MOV DX,AX ;dx gets search size
- MOV CL,4
- SHR DX,CL ;number of segments to search
- SUB SEARCH_SEGMENTS,DX ;decrease the amount to search
- ;si = string di = string size
- CALL SEARCH ;es:bx=ptr,ax=bytes to search
- JZ SEARCH_FOUND ;if zero flag, string is found
- ADD AX,1 ;next character after fail
- MOV BX,AX ;into es:bx
- JNC NOWR ;if offset rolls over
- MOV AX,ES ;add 64k
- ADD AX,1000H ;to the
- MOV ES,AX ;offset
- NOWR: CALL NORMALIZE ;set to start at the top of
- JMP LOOK_AGAIN ;a new segment
- SEARCH_NOT_FOUND:
- XOR AX,AX ;start over
- MOV ES,AX
- CMP AL,1 ;clear zero flag
- SEARCH_FOUND:
- MOV START_SEGMENT,ES ;set page
- MOV START_OFFSET,AX ;address of found string
- RET
- SEARCH_MEM ENDP
- ;-----------------------------------------------------------------
- ;si = string di = string size es:bx = pointer to buffer to search
- ;ax = number of bytes in buffer to search. Zero flag set if found
- ;-----------------------------------------------------------------
- SEARCH PROC NEAR ;si points at string
- PUSH BX
- PUSH DI
- PUSH SI
- XCHG BX,DI ;string size, ptr to data area
- MOV CX,AX ;# chars in segment to search
- BYTE_ADD:
- LODSB ;char for first part of search
- NEXT_SRCH:
- REPNZ SCASB ;is first char in string in buffer
- JNZ NOT_FOUND ;if not, no match
- PUSH DI ;save against cmpsb
- PUSH SI
- PUSH CX
- LEA CX,[BX-1] ;# chars in string - 1
- JCXZ ONE_CHAR ;if one char search, we have found it
- REP CMPSB ;otherwise compare rest of string
- ONE_CHAR:
- POP CX ;restore for next cmpsb
- POP SI
- POP DI
- JNZ NEXT_SRCH ;if zr = 0 then string not found
- NOT_FOUND:
- LEA AX,[DI-1] ;ptr to last first character found
- POP SI
- POP DI
- POP BX
- RET
- SEARCH ENDP
- ;------------------------------------------------------------------
- ;dx=row:col,cx=max len,bx=replace character,si=prompt,di=sieve
- ;------------------------------------------------------------------
- INPUT PROC NEAR
- PUSH BP ;create stack frame
- MOV BP,SP
- SUB SP,6
- CALL CURSOR_ON
- MOV [BP-2],CX ;save size of destination
- MOV [BP-4],SI
- MOV [BP-6],DX
- XOR CX,CX ;clear count of chars entered
- NEXT_DISPLAY:
- PUSH BX ;save replace char
- PUSH SI
- MOV AL,[BP-5] ;row
- CBW ;into ax
- MOV BL,[BP-6] ;col
- XOR BH,BH ;into bx
- MOV SI,[BP-4]
- CALL DISPLAY_STRING ;show string at si
- POP SI
- POP BX ;restore replace char
- PUSH DS ;set up string addressing
- POP ES
- NEXT_KEY:
- CMP BYTE PTR[SI],":";skip colon in destination
- JNZ NOT_COLON
- INC CX ;next count
- INC DL ;next col
- INC SI ;point to next char
- NOT_COLON:
- CALL SETPOS ;set cursor position
- CALL GETKEY ;get next key
- CMP AH,1 ;if scan = 1
- JZ END_OF_INPUT ;then it's esc
- CMP AH,1CH ;if scan = 1ch
- JZ END_OF_INPUT ;then it's carriage return
- CMP AH,L_ARR ;if it's left arrow
- JZ BACK_SPACE ;or
- CMP AH,0EH ;if it's backspace key
- JNZ NOT_BACK_SPACE ;then back up
- BACK_SPACE:
- JCXZ NEXT_KEY ;if count 0 can't back up
- DEC CX ;decrement count
- DEC DL ;decrement column
- DEC SI ;decrement pointer to chars
- CMP BYTE PTR[SI],":";if pointer is to colon,
- JZ BACK_SPACE ;then back up again
- MOV BYTE PTR[SI],BL ;put replace character in
- JMP NEXT_DISPLAY ;show line again
- NOT_BACK_SPACE:
- CMP CX,[BP-2] ;is count = max count
- JZ NEXT_KEY ;if so, can't put in buffer
- NEXT_INPUT:
- CALL VERIFY ;ax = char di = sieve
- JNZ NEXT_KEY ;if illegal char get new key
- MOV [SI],AL ;otherwize put in buffer
- INC CX ;next count
- INC SI ;pointer to next char
- INC DL ;next column
- JMP NEXT_DISPLAY ;show line again
- END_OF_INPUT:
- CMP BL,"0" ;if replace char is "0"
- JZ NO_ZERO ;dont put terminator in
- MOV BYTE PTR[SI],0 ;terminate string
- NO_ZERO:
- CALL CURSOR_OFF
- ADD SP,6 ;clean off stack
- POP BP
- RET
- INPUT ENDP
- ;------------------------------------------------------------------
- GETKEY PROC NEAR
- XOR AH,AH ;getkey function number
- INT 16H ;go get a key
- RET ;return it
- GETKEY ENDP
- ;------------------------------------------------------------------
- ;ax = row bx = col displays string at ds:si
- ;------------------------------------------------------------------
- DISPLAY_STRING PROC NEAR
- PUSH SI ;save si for main routines
- PUSH DI
- CALL CALC_SCRN_ADDR ;get es:di for row col
- MOV AH,7 ;get normal attribute
- NEXT_CHAR: LODSB ;get char from string
- OR AL,AL ;if zero
- JZ LAST_CHAR ;string has been printed
- STOSW ;char and attribute on screen
- JMP NEXT_CHAR ;until string has been printed
- LAST_CHAR: POP DI
- POP SI ;restore si for main routines
- RET
- DISPLAY_STRING ENDP
- ;------------------------------------------------------------------
- ;ax = row bx= col, returns es:di pointing to the screen address
- ;------------------------------------------------------------------
- CALC_SCRN_ADDR PROC NEAR
- PUSH CX
- PUSH DX ;mul destroys dx
- PUSH AX ;save ax for later
- MOV ES,CS:BIOS_SEG ;into es
- MOV AX,0B800H ;CGA screen = b800h
- CMP ES:BYTE PTR[49H],7
- JNZ COLOR ;if 40:49 == 7 then
- MOV AH,0B0H ;screen seg = b000h
- COLOR: MOV ES,AX ;into es
- POP CX ;get row
- MOV AX,160 ;160 bytes to a row of text
- ADD AX,CS:DIFF ;# characters > 80
- ADD AX,CS:DIFF ;# of attribute bytes > 80
- MUL CX ;row * 160 + diff*2
- ADD AX,BX ;+col
- ADD AX,BX ;row*160 + col*2
- MOV DI,AX ;es:di points to address
- POP DX ;restore dx
- POP CX
- RET
- CALC_SCRN_ADDR ENDP
- ;------------------------------------------------------------------
- ;ax = char di = sieve
- ;------------------------------------------------------------------
- VERIFY PROC NEAR
- PUSH CX ;save registers for main routines
- PUSH DI
- PUSH SI
- PUSH DS
- POP ES
- MOV SI,DI ;si = sieve address
- CALL STRLEN ;how many chars in sieve (cx)
- JCXZ ANY_KEY ;get key if no chars in sieve
- CMP AL,"A"
- JB NOT_SMALL
- AND AL,0DFH ;make upper case to
- NOT_SMALL: ;search for char in the sieve
- REPNZ SCASB ;set zero flag to indicate it
- ANY_KEY:
- POP SI ;restore registers
- POP DI
- POP CX
- RET
- VERIFY ENDP
- ;----------------------------------------------------------------------
- STRLEN PROC NEAR
- PUSH SI ;save si for main routines
- PUSH AX
- MOV CX,-1 ;count for string length
- NEXTS: INC CX ;next count
- LODSB ;next char
- OR AL,AL ;is it a zero
- JNZ NEXTS ;if not get next char
- POP AX
- POP SI ;restore si for main routines
- RET
- STRLEN ENDP
- ;------------------------------------------------------------------
- ;input: al = ascii lsb ah = ascii msb
- ; example: if hex is '3F', ah = '3' al = 'F' result: al = 3Fh
- ;output: al = hex byte
- ;------------------------------------------------------------------
- ASCII_HEX_TO_HEX PROC NEAR
- TEST AH,40H ;if "A" - "F"
- JZ AH_EXIT
- SUB AH,"A"-10 ;make 10-15
- AH_EXIT: TEST AL,40H ;if "A" - "F"
- JZ AL_EXIT
- SUB AL,"A"-10 ;make 10-15
- AL_EXIT: AND AX,0F0FH ;if "0" - "9"
- SHL AL,1
- SHL AL,1
- SHL AL,1
- SHL AL,1 ;make 0-9
- OR AL,AH ;combine msn and lsn
- RET
- ASCII_HEX_TO_HEX ENDP
- ;------------------------------------------------------------------
- ;input: al = char to be translated:
- ; example: if hex is '3F', al = '3' ah = 'F'
- ;output: al = msb of translation, ah = lsb of translation
- ;------------------------------------------------------------------
- HEX_TO_ASCII_HEX PROC NEAR ;CREATE MACHINE CODE to:
- DB 0D4H,10H ;div AL/16-remainder in al
- OR AX,3030H ;make ascii
- CMP AL,"9"
- JBE ALEXIT
- ADD AL,7 ;if a - f make "A" - "F"
- ALEXIT: CMP AH,"9"
- JBE AHEXIT
- ADD AH,7 ;if a - f make "A" - "F"
- AHEXIT: XCHG AL,AH
- RET
- HEX_TO_ASCII_HEX ENDP
- ;-----------------------------------------------------------------
- EVEN ; VIDEO & STACK included to insure that TSR will NOT grow!
- DB 4000 DUP ('V') ;start of memory used to save screen
- DB 4 DUP ('B') ;BackGround Processing Minimum
- DB 256 DUP ('S') ;PopUp Main Processing Stack
- TopStack LABEL BYTE ;marks end of resident code
- DB " Heart&Mind " ;identify reviser
- ;-----------------------------------------------------------------
- INSTALLED_SEGMENT DW 0
- DISABLED DB CR,LF,"RAMVIEW IS DISABLED",CR,LF,"$"
- ENABLED DB CR,LF,"RAMVIEW IS RE-ENABLED",CR,LF,"$"
- ;-----------------------------------------------------------------
- ;determine if vectors have changed since program was installed
- ;-----------------------------------------------------------------
- HOOKED_VECTORS_SAME? PROC NEAR
- MOV CX,INSTALLED_SEGMENT ;get executing segment
- XOR AX,AX ;interrupt table segment
- MOV ES,AX ;into the extra segment
- CMP CX,ES:[10h*4+2] ;If INT 10h Vector
- JNZ VECTOR_CHANGED ;Or INT 09h Vector
- CMP CX,ES:[9*4+2] ;Is NOT HERE
- VECTOR_CHANGED: ;Then NZ Flag
- RET
- HOOKED_VECTORS_SAME? ENDP
- ;-----------------------------------------------------------------
- ;determine if program is already installed
- ;-----------------------------------------------------------------
- PROGRAM_ALREADY_IN PROC NEAR
- NOT WORD PTR BEGIN ;only search for active copy
- MOV START_SEGMENT,60h ;start after DOS area
- MOV START_OFFSET,0
- MOV END_SEGMENT,CS ;stop looking before reaching
- MOV END_OFFSET,0 ;this copy in memory
- MOV SI,OFFSET BEGIN ;compare from modified bytes
- MOV CX,25 ;for enough of a text match
- CALL SEARCH_MEM ;use program's built-in proc
- PUSHF ;Preserve Search Result
- MOV AX,START_SEGMENT ;get address of find and
- MOV INSTALLED_SEGMENT,AX ;save as installed address
- MOV AX,START_OFFSET
- MOV CL,4 ;make into
- SHR AX,CL ;paragraphs
- SUB AX,10h ;less PSP
- ADD INSTALLED_SEGMENT,AX
- MOV START_SEGMENT,0 ;reset starting address
- MOV START_OFFSET,0
- MOV END_OFFSET,0Fh ;reset ending address
- MOV END_SEGMENT,0FFFFh
- POPF ;Restore Search Result
- RET
- PROGRAM_ALREADY_IN ENDP
- ;-----------------------------------------------------------------
- ;UnInstall routines
- ;-----------------------------------------------------------------
- UNINSTALL PROC NEAR
- CALL HOOKED_VECTORS_SAME?;If all vectors still hooked
- JZ UNINSTALL_OK ;Then Ok to Un-Install
- NOT WORD PTR BEGIN ;Else change disabled flag
- MOV ES,INSTALLED_SEGMENT; in the installed program
- NOT ES:DISABLE
- MOV DX,OFFSET ENABLED
- CMP ES:DISABLE,-1 ;If NOT OFF
- JNE SAY_STATUS ;Then ENABLED
- MOV DX,OFFSET DISABLED ;Else DISABLED
- SAY_STATUS: MOV AH,9
- INT 21h
- RET ;PROCEDURE EXIT
- UNINSTALL_OK:
- MOV ES,INSTALLED_SEGMENT;Get Resident's PSP
- MOV DX,ES:WORD PTR ADDR_INT9H
- MOV DS,ES:WORD PTR ADDR_INT9H+2
- MOV AX,2509h ;Restore INT 9H Vector
- INT 21h
- MOV DX,ES:WORD PTR ADDR_INT10H
- MOV DS,ES:WORD PTR ADDR_INT10H+2
- MOV AX,2510h ;Restore INT10H Vector
- INT 21h
- PUSH ES
- MOV ES,ES:[2Ch] ;Environment Segment in ES
- MOV AH,49h ;Free Environment Segment
- INT 21h
- POP ES
- MOV AH,49h ;Free Program's Memory Block
- INT 21h
- PUSH CS ;Restore Code to
- POP DS ;Data Segment Register
- MOV DX,OFFSET UNINSTALLED
- JMP SAY_STATUS
- UNINSTALL ENDP
- ;-----------------------------------------------------------------
- INSTALL PROC NEAR
- MOV CL,9 ;link vector for INT 9H
- MOV SI,OFFSET ADDR_INT9H
- MOV DI,OFFSET INT9H
- CALL INSTALL_VECTOR
- MOV CL,10h ;link vector for INT10H
- MOV SI,OFFSET ADDR_INT10H
- MOV DI,OFFSET INT10H
- CALL INSTALL_VECTOR
- RET
- INSTALL ENDP
- ;-----------------------------------------------------------------
- INSTALL_VECTOR PROC NEAR
- MOV AL,CL ;get vector number
- MOV AH,35h ;get interrupt number
- INT 21h
- MOV [SI],BX ;save interrupt vector
- MOV [SI+2],ES
- MOV DX,DI ;get replacement address
- MOV AH,25h ;set vector address
- MOV AL,CL ;for INT number
- INT 21h
- RET
- INSTALL_VECTOR ENDP
- ;-----------------------------------------------------------------
- _TEXT ENDS
- END BEGIN